from wormbane.direction import direction_to_planar_vector
from wormbane.Feature import Door, Doorway, Floor, Wall
import curses


class CursesUi(object):
    def __init__(self, stdscr):
        self.stdscr = stdscr
        self.command_shortcuts = {ord('7'): 'northwest',
                                  ord('8'): 'north',
                                  ord('9'): 'northeast',
                                  ord('4'): 'west',
                                  ord('5'): 'rest',
                                  ord('6'): 'east',
                                  ord('1'): 'southwest',
                                  ord('2'): 'south',
                                  ord('3'): 'southeast',
                                  ord('<'): 'up',
                                  ord('>'): 'down',
                                  curses.KEY_UP: 'north',
                                  curses.KEY_LEFT: 'west',
                                  curses.KEY_RIGHT: 'east',
                                  curses.KEY_DOWN: 'south',
                                  ord('c'): 'close',
                                  ord('o'): 'open',
                                  ord('Q'): 'quit',
                                  ord('s'): 'search',
                                  ord('S'): 'save'}
        self.wall_chars = {'northwest': curses.ACS_ULCORNER,
                           'north': curses.ACS_HLINE,
                           'northeast': curses.ACS_URCORNER,
                           'west': curses.ACS_VLINE,
                           None: ord(' '),
                           'east': curses.ACS_VLINE,
                           'southwest': curses.ACS_LLCORNER,
                           'south': curses.ACS_HLINE,
                           'southeast': curses.ACS_LRCORNER}
        self.door_chars = {'+': '+', # curses.ACS_PLUS,
                           '|': curses.ACS_VLINE,
                           '-': curses.ACS_HLINE}
        self.colors = {'black': curses.color_pair(curses.COLOR_BLACK),
                       'blue': curses.color_pair(curses.COLOR_BLUE),
                       'cyan': curses.color_pair(curses.COLOR_CYAN),
                       'green': curses.color_pair(curses.COLOR_GREEN),
                       'magenta': curses.color_pair(curses.COLOR_MAGENTA),
                       'red': curses.color_pair(curses.COLOR_RED),
                       'yellow': curses.color_pair(curses.COLOR_YELLOW),
                       'white': curses.color_pair(curses.COLOR_WHITE)}
        self.vitality_colors = {'good': 'green',
                                'fair': 'yellow',
                                'poor': 'red'}

    def tile_to_char(self, tile):
        if tile.top_item:
            return ord(tile.top_item.char), tile.top_item.color
        elif tile.feature:
            if type(tile.feature) is Wall:
                return self.wall_chars[tile.feature.dir], tile.feature.color
            elif type(tile.feature) is Door:
                return self.door_chars[tile.feature.char], tile.feature.color
            elif type(tile.feature) in (Floor, Doorway):
                return curses.ACS_BULLET, tile.feature.color
            else:
                return ord(tile.feature.char), tile.feature.color
        else:
            return ord(' '), 'black'

    def update_screen(self, game):
        stdscr = self.stdscr
        message_line = ' '.join(game.messages)
        stdscr.addstr(0, 0, (message_line + ' ' * 79)[:79])
        width, height = game.current_level.size
        tiles = game.current_level.tiles
        seen = game.field_of_view.contains
        lit = game.light.contains
        colors = self.colors
        tile_to_char = self.tile_to_char
        for x in xrange(width):
            for y in xrange(height):
                tile = tiles[x][y]
                seen_tile = seen(x, y)
                if (seen_tile and type(tile.feature) is Wall
                    and tile.feature.dir):
                    dir_vector = direction_to_planar_vector(tile.feature.dir)
                    line_of_sight_x = tile.pos.x - game.hero.pos.x
                    line_of_sight_y = tile.pos.y - game.hero.pos.y
                    seen_tile = (dir_vector.x * line_of_sight_x >= 0 and
                                 dir_vector.y * line_of_sight_y >= 0)
                if seen_tile and (tile.lit or lit(x, y)):
                    char, color = tile_to_char(tile)
                    tile.known = char
                    if tile.monster:
                        char, color = tile.monster.char, tile.monster.color
                else:
                    char = tile.known or ord(' ')
                    color = 'blue'
                stdscr.addch(height - y, x, char, colors[color])
        stdscr.addstr(height + 1, 0, 'Wormhole %d  ' % game.current_level.num)
        vitality_percentage = game.hero.vitality_percentage
        if vitality_percentage < 100:
            vitality_color = self.vitality_colors[game.hero.vitality_shape]
        else:
            vitality_color = 'black'
        stdscr.addstr('Vitality %d%%  ' % vitality_percentage,
                      self.colors[vitality_color])
        stdscr.move(height - game.hero.pos.y, game.hero.pos.x)

    def read_command(self):
        while True:
            ch = self.stdscr.getch()
            if ch in self.command_shortcuts:
                return self.command_shortcuts[ch]
